/*
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License");  you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * http//www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 *
 * The Original Code is ART Ontology API (AllegroGraph Implementation).
 *
 * The Initial Developer of the Original Code is University of Roma Tor Vergata.
 * Portions created by University of Roma Tor Vergata are Copyright (C) 2010.
 * All Rights Reserved.
 *
 * ART Ontology API (AllegroGraph Implementation) was developed by the Artificial Intelligence Research Group
 * (art.uniroma2.it) at the University of Roma Tor Vergata
 * Current information about the ART Ontology API (AllegroGraph Implementation) can be obtained at 
 * http//art.uniroma2.it/owlart
 *
 */
package it.uniroma2.art.owlart.agraphimpl.factory;

import it.uniroma2.art.owlart.agraphimpl.models.BaseRDFModelAllegroGraphImpl;
import it.uniroma2.art.owlart.agraphimpl.models.SKOSXLModelAllegroGraphImpl;
import it.uniroma2.art.owlart.agraphimpl.models.conf.AllegroGraph4ModelConfiguration;
import it.uniroma2.art.owlart.exceptions.ModelCreationException;
import it.uniroma2.art.owlart.exceptions.ModelUpdateException;
import it.uniroma2.art.owlart.models.BaseRDFTripleModel;
import it.uniroma2.art.owlart.models.ModelFactory;
import it.uniroma2.art.owlart.models.OWLArtModelFactory;
import it.uniroma2.art.owlart.models.OWLModel;
import it.uniroma2.art.owlart.models.RDFModel;
import it.uniroma2.art.owlart.models.RDFSModel;
import it.uniroma2.art.owlart.models.SKOSModel;
import it.uniroma2.art.owlart.models.SKOSXLModel;
import it.uniroma2.art.owlart.models.TripleQueryModelHTTPConnection;
import it.uniroma2.art.owlart.models.UnloadableModelConfigurationException;
import it.uniroma2.art.owlart.models.UnsupportedModelConfigurationException;
import it.uniroma2.art.owlart.sesame2impl.models.TripleQueryModelHTTPConnectionSesame2Impl;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;

import org.openrdf.repository.RepositoryException;
import org.openrdf.sail.SailException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.franz.agraph.repository.AGCatalog;
import com.franz.agraph.repository.AGRepository;
import com.franz.agraph.repository.AGServer;

/**
 * This class implements {@link ModelFactory}<br/>
 * 
 * A fast and easy way to load an RDF/RDFS/OWL Model by using this AllegroGraph implementation is to wrap it
 * through the OWL API convenience class {@link OWLArtModelFactory}, which handles standard configuration of
 * models of the RDF family, like loading proper vocabularies, setting baseuri/defnamespace of the loaded
 * model etc... <br/>
 * This is the code to do that:
 * 
 * <pre>
 * ModelFactory fact = OWLArtModelFactory.createModelFactory(&lt;an instance of this class&gt;);
 * </pre>
 * 
 * @author Luca Mastrogiovanni <luca.mastrogiovanni@caspur.it><br/>
 *         Armando Stellato <stellato@info.uniroma2.it> (updated to new ModelConfiguration)<br/>
 * 
 */
public class ARTModelFactoryAllegroGraphImpl implements ModelFactory<AllegroGraph4ModelConfiguration> {

	/**
	 * this is false by default, since usually users will access a repository of Allegrograph without willing
	 * to change its basic content (unless explicitly doing that)
	 */
	protected boolean populatingW3CVocabularies = false;

	protected static Logger logger = LoggerFactory.getLogger(ARTModelFactoryAllegroGraphImpl.class);

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * it.uniroma2.art.owlart.models.ModelFactory#closeModel(it.uniroma2.art.owlart.models.BaseRDFTripleModel)
	 */
	public void closeModel(BaseRDFTripleModel rep) throws ModelUpdateException {
		rep.close();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see it.uniroma2.art.owlart.models.ModelFactory#loadRDFBaseModel(java.lang.String, java.lang.String,
	 * boolean)
	 */
	public BaseRDFModelAllegroGraphImpl loadRDFBaseModel(String baseuri, String persistenceDirectory,
			AllegroGraph4ModelConfiguration conf) throws ModelCreationException {

		try {
			AGServer server = new AGServer(conf.serverURL, conf.username, conf.password);
			AGCatalog catalog = server.getCatalog(conf.agCatalogId);

			File dataDir = new File(persistenceDirectory);
			if (!dataDir.exists())
				throw new ModelCreationException("you must specify an existig directory for this repository ");

			logger.info("persistenceDirectory: " + persistenceDirectory);
			logger.info("baseuri: " + baseuri);
			logger.info("username: " + conf.username);
			logger.info("password: " + conf.password);

			logger.info("catalogId: " + catalog.getCatalogName());

			// String repositoryId =
			// persistenceDirectory.substring(persistenceDirectory.lastIndexOf("/")+1,persistenceDirectory.length());
			String repositoryId = conf.agRepositoryId;
			logger.info("repositoryId: " + repositoryId);

			// catalog.deleteRepository(REPOSITORY_ID);
			AGRepository agRepository = catalog.createRepository(repositoryId);
			agRepository.initialize();

			logger.info("AllegroGraph is initialized");

			BaseRDFModelAllegroGraphImpl rep = new BaseRDFModelAllegroGraphImpl(agRepository,
					conf.rdfsInference);

			logger.info("connection ready");

			return rep;

		} catch (SailException e) {
			e.printStackTrace();
			logger.error("An error occurred during connection to the store: " + e.getMessage());
			throw new ModelCreationException(e.getMessage());
		} catch (RepositoryException e) {
			e.printStackTrace();
			logger.error("An error occurred during connection to the store: " + e.getMessage());
			throw new ModelCreationException(e.getMessage());
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("An error occurred during connection to the store: " + e.getMessage());
			throw new ModelCreationException(e.getMessage());
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see it.uniroma2.art.owlart.models.ModelFactory#loadRDFModel(java.lang.String, java.lang.String,
	 * boolean)
	 */
	public RDFModel loadRDFModel(String baseuri, String persistenceDirectory,
			AllegroGraph4ModelConfiguration conf) throws ModelCreationException {
		BaseRDFModelAllegroGraphImpl baserep = loadRDFBaseModel(baseuri, persistenceDirectory, conf);

		SKOSXLModelAllegroGraphImpl rep = new SKOSXLModelAllegroGraphImpl(baserep);
		return rep;

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see it.uniroma2.art.owlart.models.ModelFactory#loadRDFSModel(java.lang.String, java.lang.String,
	 * boolean)
	 */
	public RDFSModel loadRDFSModel(String baseuri, String persistenceDirectory,
			AllegroGraph4ModelConfiguration conf) throws ModelCreationException {
		BaseRDFModelAllegroGraphImpl baserep = loadRDFBaseModel(baseuri, persistenceDirectory, conf);

		SKOSXLModelAllegroGraphImpl rep = new SKOSXLModelAllegroGraphImpl(baserep);
		return rep;

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see it.uniroma2.art.owlart.models.ModelFactory#loadOWLModel(java.lang.String, java.lang.String,
	 * boolean)
	 */
	public OWLModel loadOWLModel(String baseuri, String persistenceDirectory,
			AllegroGraph4ModelConfiguration conf) throws ModelCreationException {

		SKOSXLModelAllegroGraphImpl rep = (SKOSXLModelAllegroGraphImpl) loadRDFSModel(baseuri,
				persistenceDirectory, conf);
		return rep;

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see it.uniroma2.art.owlart.models.ModelFactory#loadSKOSModel(java.lang.String, java.lang.String,
	 * boolean)
	 */
	public SKOSModel loadSKOSModel(String baseuri, String persistenceDirectory,
			AllegroGraph4ModelConfiguration conf) throws ModelCreationException {

		SKOSXLModelAllegroGraphImpl rep = (SKOSXLModelAllegroGraphImpl) loadRDFSModel(baseuri,
				persistenceDirectory, conf);
		return rep;

	}

	public SKOSXLModel loadSKOSXLModel(String baseuri, String persistenceDirectory,
			AllegroGraph4ModelConfiguration conf) throws ModelCreationException {

		SKOSXLModelAllegroGraphImpl rep = (SKOSXLModelAllegroGraphImpl) loadRDFSModel(baseuri,
				persistenceDirectory, conf);
		return rep;

	}

	public <MCImpl extends AllegroGraph4ModelConfiguration> MCImpl createModelConfigurationObject(
			Class<MCImpl> mcclass) throws UnsupportedModelConfigurationException,
			UnloadableModelConfigurationException {
		if (mcclass == AllegroGraph4ModelConfiguration.class) {
			try {
				return mcclass.newInstance();
			} catch (InstantiationException e) {
				throw new UnloadableModelConfigurationException(mcclass);
			} catch (IllegalAccessException e) {
				throw new UnloadableModelConfigurationException(mcclass);
			}
		} else
			throw new UnsupportedModelConfigurationException(this, mcclass);

	}

	public Collection<Class<? extends AllegroGraph4ModelConfiguration>> getModelConfigurations() {
		ArrayList<Class<? extends AllegroGraph4ModelConfiguration>> arr = new ArrayList<Class<? extends AllegroGraph4ModelConfiguration>>();
		arr.add(AllegroGraph4ModelConfiguration.class);
		return arr;
	}

	public TripleQueryModelHTTPConnection loadTripleQueryHTTPConnection(String endpointURL)
			throws ModelCreationException {
		return new TripleQueryModelHTTPConnectionSesame2Impl(endpointURL);
	}

	public void setPopulatingW3CVocabularies(boolean pref) {
		populatingW3CVocabularies = pref;
	}

	public boolean isPopulatingW3CVocabularies() {
		return populatingW3CVocabularies;
	}

}
